import org.junit.Test;

import java.io.*;

/**
 * 数据流 DataOutputStream / DataInputStream
 * - 允许应用程序将基本数据类型、String类型的变量写入输出流中。
 * - 允许应用程序以与机器无关的方式从底层输入流中读取基本数据类型、String类型的变量。
 * <p>
 * 对象流 ObjectOutputStream / ObjectInputStream
 * - 可以读写基本数据类型的变量、引用数据类型的变量
 * <p>
 * 对象的序列化机制
 * 对象序列化机制允许把内存中的Java对象转化成平台无关的二进制流，从而允许把这种二进制文流持久地保存在磁盘上，
 * 或通过网络将这种二进制流传输到另一个网络节点。（序列化过程，使用ObjectOutputStream流实现。）
 * // 当其他程序获取了这种二进制流，就可以恢复成原来的Java对象。（反序列化过程，使用ObjectInputStream流实现）。
 * <p>
 * 自定义类要想实现序列化机制，需要满足：
 * ① 自定义类需要实现接口：Serializable
 * ② 要求自定义类声明一个全局常量：static final long serialVersionUID = 7123498L;
 * --  如果不声明全局常量serialVersionUID，系统会自动声明生成一个针对于当前类的serialVersionUID。
 * --  如果修改此类的话，会导致serialVersionUID变化，进而导致反序列化时，出现InvalidClassException异常。
 * ③ 要求自定义类的各个属性也必须是可序列化的。
 * --> 对于基本数据类型，默认就是可序列化的
 * --> 对于引用数据类型，需要实现接口：Serializable
 * ④ 类中的属性如果声明为transient或static，则不会实现序列化。
 */
public class ObjectStreamTest {
    // 序列化
    @Test
    public void testObjectOutputStream() {
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("object.txt"))) {
            objectOutputStream.writeUTF("I am IronMan");
//            objectOutputStream.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void testObjectInputStream() {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"))) {
            String s = ois.readUTF();
            System.out.println(s);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void testPerson() {
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("Person.data"))) {
            objectOutputStream.writeObject(new Person("Tom", 12));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 反序列化
    @Test
    public void testPersonInput() {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Person.data"))) {
            Person person = (Person) ois.readObject();
            System.out.println(person);
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}
